﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WeatherData
{
    public class PlainLanguageMetarParser : IMetarParser
    {
        public MetarParserOptions Options { get; private set; }

        private StringBuilder sb = new StringBuilder();
        private Metar currentReport;
        
        public PlainLanguageMetarParser()
        {
            this.Options = new MetarParserOptions();
            this.Options.UseCelsius = false;
        }

        public string Parse(Metar report)
        {
            this.sb = new StringBuilder();
            this.currentReport = report;

            if (this.currentReport.Results > 0)
            {
                this.AppendMetarHeader();
                this.AppendWindConditions();
                this.AppendVisibility();
                this.AppendSkyConditions();
                this.AppendTemperatureAndDewpoint();
                this.AppendAltimeter();
            }
            else
            {
                sb.AppendFormat("METAR for {0} unavailable.", report.StationId);
            }

            return sb.ToString();
        }
        public Metar RawData
        {
            get { return this.currentReport; }
        }

        private void AppendMetarHeader()
        {
            this.sb.AppendFormat("Automated weather information for {0}; observed at {1}.  ",
                this.currentReport.StationId.ToUpper(),
                this.currentReport.ObservationTime.ToShortTimeString());
        }
        private void AppendTemperatureAndDewpoint()
        {
            if (this.Options.UseCelsius)
                this.sb.AppendFormat("The current temperature is {0:###}C and the dew point is {1:###}C.  ",
                    currentReport.Temperature,
                    currentReport.DewPoint);
            else
                this.sb.AppendFormat("The current temperature is {0:###}F and the dew point is {1:###}F.  ",
                    Conversions.CelsiusToFahrenheit(currentReport.Temperature),
                    Conversions.CelsiusToFahrenheit(currentReport.DewPoint));
        }
        private void AppendSkyConditions()
        {
            if (this.currentReport.SkyConditions.Count == 0)
            {
                sb.AppendLine("Sky conditions not reported.  ");
                return;
            }

            sb.Append("Sky conditions: ");
            sb.Append(String.Join<SkyCondition>(", ", this.currentReport.SkyConditions));
            sb.Append(".  ");
        }
        private void AppendWindConditions()
        {
            if (this.currentReport.WindSpeed > 0)
            {
                sb.AppendFormat("Winds are from {0:000} degrees at {1:#} knots",
                    this.currentReport.WindDirection,
                    this.currentReport.WindSpeed);
                if (this.currentReport.WindGusts > 0)
                    sb.AppendFormat(" gusting to {0:#} knots", this.currentReport.WindGusts);
            }
            else
            {
                sb.Append("Winds are calm");
            }
        }
        private void AppendVisibility()
        {
            sb.AppendFormat(" with {0:#} statute miles of visibility.  ", 
                this.currentReport.Visibility);
        }
        private void AppendAltimeter()
        {
            sb.AppendFormat("Current altimeter: {0:##.##}.  ", this.currentReport.Altimeter);
        }
    }
}
